package edu.scau.mis.system.security.config;

import edu.scau.mis.system.security.filter.MisAuthenticationTokenFilter;
import edu.scau.mis.system.security.handler.AuthenticationEntryPointImpl;
import edu.scau.mis.system.security.handler.LogoutSuccessHandlerImpl;
import edu.scau.mis.system.security.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private AuthenticationEntryPointImpl unauthorizedHandler;

    @Autowired
    private LogoutSuccessHandlerImpl logoutSuccessHandler;

    @Autowired
    private MisAuthenticationTokenFilter misAuthenticationTokenFilter;

    /* 不受控静态资源RUL */
    private static final String[] SECURITY_IGNORE_RESOURCE_URL = {
            // "/*.html", "/**/*.html" // 本项目前后端分离，无静态资源
    };
    /* 不受控API_PATH */
    private static final String[] SECURITY_IGNORE_API_PATH = {
            //  "/category/**", "/product/**", // 白名单API,绕过登录方便开发测试
            "/auth/login"
    };

    private final UserDetailsServiceImpl userDetailsService;

    @Autowired
    public SecurityConfiguration(UserDetailsServiceImpl userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    /* 用户认证管理器 */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /* 配置token验证过滤器 */
        http.addFilterBefore(misAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        /* 认证失败处理 */
        http.exceptionHandling().authenticationEntryPoint(unauthorizedHandler);

        /* 配置退出 */
        http.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); // 配置退出路径

        /* 解决跨域 */
        http.cors();

        /* 禁用跨站请求伪造csrf */
        http.csrf().disable();

        /* 后期配置JWT token后禁用session */
        // http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        /* 配置认证授权 */
        http.authorizeRequests()
                .antMatchers(HttpMethod.GET, SECURITY_IGNORE_RESOURCE_URL).permitAll() // 允许GET请求静态资源
                .antMatchers(SECURITY_IGNORE_API_PATH).permitAll() // 允许白名单API
                .anyRequest().authenticated(); // 其他请求都需要身份认证

        /* 配置登录 */
//        http.formLogin().loginProcessingUrl("/login"); //配置SSF默认表单登录，路径为/login

        /* 配置退出 */
        http.logout().logoutUrl("/logout"); // 配置退出路径
    }

    /* 配置密码加密 */
    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        /* 配置数据库用户认证 */
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }
}